package xx.services.util.img;

import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;

/** */
/**
 * @author <a href="mailto:lqinglong@yahoo.cn">qinglong.lu</a> 2008-3-21
 */
public class CutImage
{
    public static final int LEFT_TOP = 1;

    public static final int LEFT_CENTER = 2;

    public static final int LEFT_BOTTOM = 3;

    public static final int RIGHT_TOP = 4;

    public static final int RIGHT_CENTER = 5;

    public static final int RIGHT_BOTTOM = 6;

    public static final int MIDDLE_TOP = 7;

    public static final int MIDDLE_CENTER = 8;

    public static final int MIDDLE_BOTTOM = 9;

    // ===图片保存文件夹地址
    private String storeFolder = null;

    // ===源图宽度
    private int width;

    private int height;

    private FileInputStream fis = null;

    public CutImage(InputStream is) throws IOException
    {
        this.init(is);
    }

    public CutImage(String filePath) throws IOException
    {
        this.init(filePath);
    }

    public void init(InputStream is) throws IOException
    {
        Image img = ImageIO.read(is);// 构造Image对象
        this.width = img.getWidth(null); // 得到源图宽
        this.height = img.getHeight(null); // 得到源图长
        this.fis = (FileInputStream) is;
        img.flush();
    }

    public void init(String filePath) throws IOException
    {
        File file = new File(filePath); // 读入文件
        Image img = ImageIO.read(file); // 构造Image对象
        this.width = img.getWidth(null); // 得到源图宽
        this.height = img.getHeight(null); // 得到源图长
        this.fis = new FileInputStream(filePath);
        img.flush();
    }

    /**
     * 对图片裁剪，并把裁剪完的新图片保存 。<br>
     * 默认居中裁剪
     * 
     * @param width
     *            宽度
     * @param height
     *            高度
     * @return
     * @throws IOException
     */
    public File cut(int width, int height) throws IOException
    {
        if (width >= this.width && height >= this.height)
        {
            return null;
        }

        int x = width >= this.width ? 0 : (this.width - width) / 2;
        int y = height >= this.height ? 0 : (this.height - height) / 2;

        return cut(width, height, x, y);
    }

    /**
     * 对图片裁剪，并把裁剪完的新图片保存 。<br>
     * 需要指定裁剪的位置
     * 
     * @param width
     *            宽度
     * @param height
     *            高度
     * @param position
     *            位置，取值为：<br>
     *            CutImage.LEFT_TOP = 1;<br>
     *            CutImage.LEFT_CENTER = 2;<br>
     *            CutImage.LEFT_BOTTOM = 3;<br>
     *            CutImage.RIGHT_TOP = 4;<br>
     *            CutImage.RIGHT_CENTER = 5;<br>
     *            CutImage.RIGHT_BOTTOM = 6;<br>
     *            CutImage.MIDDLE_TOP = 7;<br>
     *            CutImage.MIDDLE_CENTER = 8;<br>
     *            CutImage.MIDDLE_BOTTOM = 9;<br>
     * @return
     * @throws IOException
     */
    public File cut(int width, int height, int position) throws IOException
    {
        if (width >= this.width && height >= this.height)
        {
            return null;
        }

        int x, y;

        switch (position)
        {
            case LEFT_TOP:
                x = 0;
                y = 0;
                break;
            case LEFT_CENTER:
                x = 0;
                y = height >= this.height ? 0 : (this.height - height) / 2;
                break;
            case LEFT_BOTTOM:
                x = 0;
                y = height >= this.height ? 0 : (this.height - height);
                break;
            case MIDDLE_TOP:
                x = width >= this.width ? 0 : (this.width - width) / 2;
                y = 0;
                break;
            case MIDDLE_CENTER:
                x = width >= this.width ? 0 : (this.width - width) / 2;
                y = height >= this.height ? 0 : (this.height - height) / 2;
                break;
            case MIDDLE_BOTTOM:
                x = width >= this.width ? 0 : (this.width - width) / 2;
                y = height >= this.height ? 0 : (this.height - height);
                break;
            case RIGHT_TOP:
                x = width >= this.width ? 0 : (this.width - width);
                y = 0;
                break;
            case RIGHT_CENTER:
                x = width >= this.width ? 0 : (this.width - width);
                y = height >= this.height ? 0 : (this.height - height) / 2;
                break;
            case RIGHT_BOTTOM:
                x = width >= this.width ? 0 : (this.width - width);
                y = height >= this.height ? 0 : (this.height - height);
                break;
            default:
                return cut(width, height);
        }

        return cut(width, height, x, y);
    }

    /**
     * 设置图片保存文件夹地址，默认为系统临时目录
     * 
     * @param storeFolder
     */
    public void setStoreFolder(String storeFolder)
    {
        this.storeFolder = storeFolder;
    }

    private File createTmpFile() throws IOException
    {
        return this.storeFolder != null && !"".equals(this.storeFolder) ? File.createTempFile(
                "img", ".jpg", new File(this.storeFolder)) : File.createTempFile("img", ".jpg");
    }

    /**
     * 对图片裁剪，并把裁剪完的新图片保存 。
     */
    private File cut(int width, int height, int x, int y) throws IOException
    {

        final FileInputStream fis = this.fis;
        ;

        // 获取图片流
        final ImageInputStream iis = ImageIO.createImageInputStream(fis);

        try
        {
            // if (this.fis.markSupported())
            // this.fis.reset();
            // this.fis.mark(0);
            /**//*
                  * 返回包含所有当前已注册 ImageReader 的 Iterator，这些 ImageReader 声称能够解码指定格式。 参数：formatName -
                  * 包含非正式格式名称 . （例如 "jpeg" 或 "tiff"）等 。
                  */
            Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName("jpg");
            ImageReader reader = it.next();

            // iis =

            /**//*
                  * <p>iis:读取源.true:只向前搜索 </p>.将它标记为 ‘只向前搜索’。 此设置意味着包含在输入源中的图像将只按顺序读取，可能允许 reader
                  * 避免缓存包含与以前已经读取的图像关联的数据的那些输入部分。
                  */
            reader.setInput(iis, true);

            /**//*
                  * <p>描述如何对流进行解码的类<p>.用于指定如何在输入时从 Java Image I/O 框架的上下文中的流转换一幅图像或一组图像。用于特定图像格式的插件
                  * 将从其 ImageReader 实现的 getDefaultReadParam 方法中返回 ImageReadParam 的实例。
                  */
            ImageReadParam param = reader.getDefaultReadParam();

            /**//*
                  * 图片裁剪区域。Rectangle 指定了坐标空间中的一个区域，通过 Rectangle 对象 的左上顶点的坐标（x，y）、宽度和高度可以定义这个区域。
                  */
            Rectangle rect = new Rectangle(x, y, width, height);

            // 提供一个 BufferedImage，将其用作解码像素数据的目标。
            param.setSourceRegion(rect);

            /**//*
                  * 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象，并将 它作为一个完整的 BufferedImage 返回。
                  */
            BufferedImage bi = reader.read(0, param);

            File file = this.createTmpFile();

            // 保存新图片
            ImageIO.write(bi, "jpg", file);

            return file;
        }

        finally
        {
            if (iis != null)
                iis.close();
            if (fis != null)
                fis.close();
        }

    }

    public int getHeight()
    {
        return height;
    }

    public int getWidth()
    {
        return width;
    }

    public static void main(String[] args) throws Exception
    {
        long time1 = System.currentTimeMillis();
        System.out.println("Start:" + time1);
        String name = "d:/4.jpg";

        Thumbnail thum = new Thumbnail(name, "d:/tmp");
        File file = thum.resizeFix(200, 200);
        thum = null;

        String cPath = file.getPath();

        int width = 100, height = 100;
        CutImage o = new CutImage(cPath);
        o.setStoreFolder("d:/tmp");
        o.cut(100, 100);
        o.cut(width, height, CutImage.LEFT_TOP);
        o.cut(width, height, CutImage.LEFT_CENTER);
        o.cut(width, height, CutImage.LEFT_BOTTOM);
        o.cut(width, height, CutImage.MIDDLE_TOP);
        o.cut(width, height, CutImage.MIDDLE_CENTER);
        o.cut(width, height, CutImage.MIDDLE_BOTTOM);
        o.cut(width, height, CutImage.RIGHT_TOP);
        o.cut(width, height, CutImage.RIGHT_CENTER);
        o.cut(width, height, CutImage.RIGHT_BOTTOM);

        long time2 = System.currentTimeMillis();
        System.out.println("End:" + time2);

        System.out.println("Time:" + (time2 - time1));

        System.out.println("OK");
    }

}
